#include "llcomp_llc.h"
typedef  struct Body_struct{  double mass;  double pos [2];  double vel [2];}  Body;
 Body *init_bodies(  unsigned int num_bodies,  int init_type) 
{

      int   i;
      double   n = num_bodies;
      Body   *  bodies = (Body *)(malloc(num_bodies * sizeof( Body ) ) );
  for (i= 0; i < num_bodies; (i++ ))  
{

    switch (init_type)
{

  case 0 : bodies[i].mass = 1.0;
bodies[i].pos [0]= i / n;
bodies[i].pos [1]= i / n;
bodies[i].vel [0]= 0.0;
bodies[i].vel [1]= 0.0;
  break ;
  case 1 : bodies[i].mass = (n - i) / n;
bodies[i].pos [0]= ((1 + (i / n)) * cos(((2 * M_PI) * i) / n) ) / 2;
bodies[i].pos [1]= ((1 + (i / n)) * sin(((2 * M_PI) * i) / n) ) / 2;
bodies[i].vel [0]= 0.0;
bodies[i].vel [1]= 0.0;
  break ;
}

;
  }

 ;
  return bodies;
}

;
 int check_simulation(  Body *bodies,  int num_bodies) 
{

      int   i;
      int   check_ok;
    double momentum [2] = {0.0,0.0 };
  for (i= 0; i < num_bodies; (i++ ))  
{

momentum[0]+= bodies[i].mass  * bodies[i].vel [0];
momentum[1]+= bodies[i].mass  * bodies[i].vel [1];
  }

 ;
check_ok= (abs(momentum[0])  < 1e-12) && (abs(momentum[1])  < 1e-12);
  if   (  (!check_ok   )  ) printf  ("Warning: total momentum = (%3.3f, %3.3f)\n"  ,momentum[0]  ,momentum[1]  )   ;;
  return check_ok;
}

;
 int llc_main(  int argc,  char **argv) 
{

      struct timeval    start_time;
      struct timeval    end_time;
      double   time;
      int   num_bodies;
      int   num_steps;
      int   i;
      int   j;
      int   k;
      double   dt = 1.0;
    double dv [2];
    double r [2];
      double   dist;
      double   force_len;
    double force_ij [2];
    double tot_force_i [2];
      Body   *  bodies;
   const char Usage [] = "Usage: nbody <num bodies> <num_steps>\n";
  if   (argc < 2  )   
{

fprintf    (stderr    ,Usage    ) ;
exit    (1    ) ;
  }

;
num_bodies= atoi(argv[1]) ;
num_steps= atoi(argv[2]) ;
bodies= init_bodies(num_bodies,1) ;
check_simulation  (bodies  ,num_bodies  ) ;
gettimeofday  ((&start_time )  ,0  ) ;
  for (k= 0; k < num_steps; (k++ ))  
{

    #pragma omp    
;
    
{

loopParallelFor0_support      ((&num_bodies )      ,(&dist )      ,r      ,(&j )      ,bodies      ,(&dt )      ,(&i )      ,(&force_len )      ,tot_force_i      ,dv      ,force_ij      ) ;
    }

;
  }

 ;
gettimeofday  ((&end_time )  ,0  ) ;
time= end_time.tv_sec  - start_time.tv_sec ;
time= time + ((end_time.tv_usec  - start_time.tv_usec ) / 1e6);
check_simulation  (bodies  ,num_bodies  ) ;
printf  ("%d:%f\n"  ,LLC_NAME  ,time  ) ;
  return 0;
}

;
 int main(  int argc,  char **argv) 
{

      int   llc_return_code = 0;
MPI_Init  ((&argc )  ,(&argv )  ) ;
MPI_Comm_rank  (MPI_COMM_WORLD  ,(int *)((&LLC_GLOBAL_NAME ))  ) ;
MPI_Comm_size  (MPI_COMM_WORLD  ,(int *)((&LLC_GLOBAL_NUMPROCESSORS ))  ) ;
LLC_NAME= LLC_GLOBAL_NAME;
LLC_NUMPROCESSORS= LLC_GLOBAL_NUMPROCESSORS;
llc_GlobalGroup= MPI_COMM_WORLD;
llc_CurrentGroup= (&llc_GlobalGroup );
llc_return_code= llc_main(argc,argv) ;
MPI_Finalize  (   ) ;
  return llc_return_code;
}

;
